﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using NeuralNetwork.Generic;
using NeuralNetwork.Activation;
using NeuralNetwork.Normalization;
using NeuralNetwork.OutputTypes;

namespace NeuralNetworkGUI
{
    public partial class frmImageRecognition : Form
    {
        private Factory<Function> functions = new Factory<Function>();
        private Factory<NormalizeFunction> normalizations = new Factory<NormalizeFunction>();
        private List<Output> outputs = null;

        public int InputNeurons
        {
            get { return Convert.ToInt32(userInputWidth.Value) * Convert.ToInt32(userInputHeight.Value); }
        }

        public int InputWidth
        {
            get { return Convert.ToInt32(userInputWidth.Value); }
        }

        public int InputHeight
        {
            get { return Convert.ToInt32(userInputHeight.Value); }
        }

        public int HiddenLayers
        {
            get { return Convert.ToInt32(userNofHiddenLayers.Value); }
        }

        public int NeuronsInHiddenLayers
        {
            get { return Convert.ToInt32(userNeuronsPerLayer.Value); }
        }

        public NormalizeFunction Normalization
        {
            get 
            {
                if (cbxNormalization.Text.ToUpper() == "NONE")
                    return null;
                else
                    return normalizations.Make(cbxNormalization.Text);
            }
        }

        public Function ActivationFunction
        {
            get { return functions.Make(cbxActivation.Text); }
        }

        public DialogResult ShowDialog(List<Output> outputs)
        {
            this.outputs = outputs;
            this.lsbOutputs.Items.Clear();
            return this.ShowDialog();
        }

        public frmImageRecognition()
        {
            InitializeComponent();
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            string s;
            outputs.Clear();            
            for (int i = 0; i < lsbOutputs.Items.Count; i++)
            {
                s = lsbOutputs.Items[i].ToString();
                outputs.Add(new GenericOutput<string>(s));
            }

            this.DialogResult = DialogResult.OK;
        }

        private void frmNewNetwork_Shown(object sender, EventArgs e)
        {
            cbxNormalization.Items.Clear();
            cbxNormalization.Items.Add("None");
            foreach (string s in normalizations.List())
                cbxNormalization.Items.Add(s);
            cbxNormalization.SelectedIndex = 0;


            cbxActivation.Items.Clear();
            foreach (string s in functions.List())
                cbxActivation.Items.Add(s);
            if (cbxActivation.Items.Count > 0) cbxActivation.SelectedIndex = 0;
            
        }

        private void AddIfNotexist(string s)
        {
            bool found = false;
            for (int i = 0; i < lsbOutputs.Items.Count; i++)
            {                
                if (lsbOutputs.Items[i].ToString() == s) found = true;
            }
            if (!found) lsbOutputs.Items.Add(s);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                // Check if should be cleared
                if (lsbOutputs.Items.Count > 0) 
                {
                    DialogResult rc = MessageBox.Show("Should the list be cleared before adding any new elements?", 
                                        "Clear list?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (rc == DialogResult.Yes) lsbOutputs.Items.Clear();
                }
                
                // Add new items and determine input size
                Bitmap image = null;
                int width = -1;
                int height = -1;
                string name = "";
                foreach (string f in Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.bmp"))
                {
                    name = Path.GetFileName(f); 
                    AddIfNotexist(name.Substring(0, name.IndexOf(".")));
                    
                    image = new Bitmap(f);
                    if (width < image.Width) width = image.Width;
                    if (height < image.Height) height = image.Height;             
                }
                if (width > 0) userInputWidth.Value = width;  
                if (height > 0) userInputHeight.Value = height;

                // Set defaults value
                userNofHiddenLayers.Value = 1;
                userNeuronsPerLayer.Value = Convert.ToInt32((double)(2.0 * width * height) / 3.0) + lsbOutputs.Items.Count;

                // Valid Network config?
                btnOk.Enabled = (lsbOutputs.Items.Count > 0);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            frmInputBox frm = new frmInputBox();
            if (frm.ShowDialog() == DialogResult.OK)
            {
                AddIfNotexist(frm.EnteredText);

                // Valid Network config?
                btnOk.Enabled = (lsbOutputs.Items.Count > 0);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (lsbOutputs.SelectedIndex >= 0)
            {
                lsbOutputs.Items.RemoveAt(lsbOutputs.SelectedIndex);

                // Valid Network config?
                btnOk.Enabled = (lsbOutputs.Items.Count > 0);
            }
        }        
    }
}
